package com.sx.micowell.framework.serialPort;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.serialport.SerialPort;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.databinding.ViewDataBinding;

import com.example.mvvm.until.LogUtils;
import com.sx.micowell.R;
import com.sx.micowell.framework.app.MyActivity;
import com.sx.micowell.framework.model.SportEndModel;
import com.sx.micowell.framework.model.SportModel;
import com.sx.micowell.framework.tools.CalcuUtils;
import com.sx.micowell.framework.tools.cmd.CmdException;
import com.sx.micowell.framework.tools.cmd.CmdUntil;
import com.sx.micowell.module.sport.SportReceive;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * @Description
 * @Author 梁浩文
 * @Date 2021/9/7 11:18
 */
public abstract class SerialPortActivity<B extends ViewDataBinding> extends MyActivity<B> {
    protected SerialPort mSerialPort;
    protected OutputStream mOutputStream;
    public InputStream mInputStream;
    private ReadThread mReadThread;
    public Integer currentCount = 0;

    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while (!isInterrupted()) {
                int size;
                try {
                    byte[] buffer = new byte[64];
                    if (mInputStream == null) return;
                    size = mInputStream.read(buffer);
                    if (size > 0) {
                        String s = ByteUtil.bytes2HexString(buffer, size);
                        Log.i(TAG, "run: " + s);
                        ArrayList<Integer> resp = ByteUtil.getResp(s);
                        if (resp != null) {
                            boolean checkLow8 = ByteUtil.checkLow8(resp);
                            if (checkLow8) {
                                //todo 这里需要处理报警
                                Integer count = resp.get(1);
                                if (count != currentCount) {
                                    currentCount = count;
                                    upDataCount(currentCount);
                                }
                                int s1 = ByteUtil.parseHex4(ByteUtil.getTenToHex(resp.get(3)) + ByteUtil.getTenToHex(resp.get(4)));
                                Log.i("onDataReceived", "当前电机转速: " + s1);
                                int s2 = ByteUtil.parseHex4(ByteUtil.getTenToHex(resp.get(5)) + ByteUtil.getTenToHex(resp.get(6)));
                                Log.i("onDataReceived", "电机力矩: " + s2);
                                int s3 = ByteUtil.parseHex4(ByteUtil.getTenToHex(resp.get(8)) + ByteUtil.getTenToHex(resp.get(9)));
                                Log.i("onDataReceived", "电机功率: " + s3);
                                onDataReceived(s1,s2,s3);
//                                if (emitter != null && !emitter.isCancelled()) {
//                                    emitter.onNext(new SportReceive(s1, s2, s3));
//                                }
                                errorList(CmdUntil.getCmdExceptionList(resp.get(0)));
                            }
                        }
                        LogUtils.i(s);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            mSerialPort = SerialPortDevices.Companion.getInstance().getSerialPort();
            mOutputStream = mSerialPort.getOutputStream();
            mInputStream = mSerialPort.getInputStream();

            /* Create a receiving thread */
            mReadThread = new ReadThread();
            mReadThread.start();
        } catch (SecurityException e) {
            DisplayError(R.string.error_security);
        } catch (InvalidParameterException e) {
            DisplayError(R.string.error_configuration);
        }
    }

    private void DisplayError(int resourceId) {
        AlertDialog.Builder b = new AlertDialog.Builder(this);
        b.setTitle("Error");
        b.setMessage(resourceId);
        b.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
//                SerialPortActivity.this.finish();
            }
        });
        b.show();
    }

    protected abstract void upDataCount(Integer count);

    protected abstract void onDataReceived(Integer speed, Integer moment, Integer power);

    protected abstract void errorList(List<CmdException> cmdExceptions);

    public void send(int... aaaa) {
        try {
            Log.i(TAG, "send: " + aaaa[0] + "-" + aaaa[1] + "-" + aaaa[2] + "-" + aaaa[3]);
            String result = ByteUtil.BuildUp(aaaa[0], aaaa[1], aaaa[2], aaaa[3], aaaa[4]);
            Log.i(TAG, "send: " + result);
            byte[] bytes = ByteUtil.parseHexStr2Byte(result);
            mOutputStream.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将int数值转换为占四个字节的byte数组，本方法适用于(低位在前，高位在后)的顺序。 和bytesToInt（）配套使用
     *
     * @param value 要转换的int值
     * @return byte数组
     */
    public byte[] intToBytes(int value) {
        byte[] src = new byte[4];
        src[3] = (byte) ((value >> 24) & 0xFF);
        src[2] = (byte) ((value >> 16) & 0xFF);
        src[1] = (byte) ((value >> 8) & 0xFF);
        src[0] = (byte) (value & 0xFF);
        return src;
    }

    @Override
    public void onDestroy() {
        stop();
        super.onDestroy();
    }

    public void stop(){
        if (mReadThread != null) mReadThread.interrupt();
        SerialPortDevices.Companion.getInstance().closeSerialPort();
        mSerialPort = null;
//        if (subscribe != null) {
//            subscribe.dispose();
//        }
    }

//    public FlowableEmitter<SportReceive> emitter;
//    public Disposable subscribe;

//    public void bufferSee(SportModel sportModel) {
//        subscribe = Flowable.create(new FlowableOnSubscribe<SportReceive>() {
//            @Override
//            public void subscribe(@NotNull FlowableEmitter<SportReceive> Tempemitter) throws Exception {
//                emitter = Tempemitter;
//            }
//        }, BackpressureStrategy.DROP)
//                .buffer(150, TimeUnit.MILLISECONDS)
//                .subscribeOn(Schedulers.io())
//                .observeOn(Schedulers.computation())
//                .subscribe(new Consumer<List<SportReceive>>() {
//                    @Override
//                    public void accept(List<SportReceive> sportReceives){
//                        //计算卡路里
//                        BigDecimal calories = BigDecimal.ZERO;
//                        for (SportReceive sportReceive : sportReceives) {
//                            BigDecimal bigDecimal = CmdUntil.countCalories(sportReceive.power);
//                            calories = calories.add(bigDecimal).setScale(4, BigDecimal.ROUND_HALF_UP);
//                        }
//                        BigDecimal finalCalories = calories;
//                        HANDLER.post(() -> {
//                            sportModel.sportList.setValue(sportReceives);
//                            sportModel.cacheCalories(finalCalories);
//                        });
//
//
//                    }
//                }, new Consumer<Throwable>() {
//                    @Override
//                    public void accept(Throwable throwable) throws Exception {
//
//                    }
//                });
//    }


}
